﻿// -----------------------------------------------------------------------
// <copyright file="BinaryStreamEx.cs" company="none">
// Copyright (c) 2012 M. Alberti, xanatos(at)live.it
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// </copyright>
// -----------------------------------------------------------------------

namespace FluentSerializer.Utilities
{
    using System;

    /// <summary>
    /// 
    /// </summary>
    public static class BinaryStreamEx
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public static long Read7BitEncoded(this BinaryReaderStream reader)
        {
            long value = 0;
            int shift = 0;

            while (true)
            {
                byte b = reader.ReadFixedByte();

                value |= ((long)(b & 127)) << shift;

                if ((b & 128) == 0)
                {
                    return value;
                }

                shift += 7;

                if (shift == 70)
                {
                    throw new FormatException();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        public static void Write7BitEncoded(this BinaryWriterStream writer, long value)
        {
            if (value < 0)
            {
                throw new ArgumentOutOfRangeException("value");
            }

            while (value >= 128)
            {
                writer.Write((byte)((value & 127) | 128));
                value >>= 7;
            }

            writer.Write((byte)value);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int SizeOf7BitEncoded(this long value)
        {
            if (value < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            int length = 1;

            while (value >= 128)
            {
                length++;
                value >>= 7;
            }

            return length;
        }
    }
}